#include "OLED.h"

static void OLED_SetPos(uint8_t X, uint8_t Y); // 声明OLED_SetPos函数

/*
 * 作用:  OLED设置光标位置
 * 参数:  无
 * 返回值:无
 */
void OLED_Init(void)
{
    delay_ms(100); // 必须要有延时

    IIC1_OLED_Init(); // 端口初始化

    OLED_WriteCmd(0xAE); // 关闭显示
    OLED_WriteCmd(0x20); // 设置内存地址模式
    OLED_WriteCmd(0x10); // 00, 水平寻址模式；01, 垂直寻址模式；10, 页面寻址模式 (RESET)；11, 无效
    OLED_WriteCmd(0xb0); // 设置页面寻址模式的页起始地址，0-7
    OLED_WriteCmd(0xc8); // 设置COM输出扫描方向
    OLED_WriteCmd(0x00); // ---设置低列地址
    OLED_WriteCmd(0x10); // ---设置高列地址
    OLED_WriteCmd(0x40); // --设置起始行地址
    OLED_WriteCmd(0x81); // --设置对比度控制寄存器
    OLED_WriteCmd(0xff); // ；亮度调节 0x00~0xff
    OLED_WriteCmd(0xa1); // --设置段重新映射 0 到 127
    OLED_WriteCmd(0xa6); // --设置正常显示
    OLED_WriteCmd(0xa8); // --设置复用比率(1到64)
    OLED_WriteCmd(0x3F); //
    OLED_WriteCmd(0xa4); // 0xa4, 输出跟随RAM内容；0xa5, 输出忽略RAM内容
    OLED_WriteCmd(0xd3); //-设置显示偏移
    OLED_WriteCmd(0x00); //-不偏移
    OLED_WriteCmd(0xd5); //--设置显示时钟分频比/振荡器频率
    OLED_WriteCmd(0xf0); //--设置分频比
    OLED_WriteCmd(0xd9); //--设置预充电周期
    OLED_WriteCmd(0x22); //
    OLED_WriteCmd(0xda); //--设置COM引脚硬件配置
    OLED_WriteCmd(0x12);
    OLED_WriteCmd(0xdb); //--设置vcomh
    OLED_WriteCmd(0x20); // 0x20, 0.77xVcc
    OLED_WriteCmd(0x8d); //--设置DC-DC使能
    OLED_WriteCmd(0x14); //
    OLED_WriteCmd(0xaf); //--打开OLED面板
}

/**
 * 作用: 将OLED从休眠中唤醒
 * 参数: 无
 * 返回值: 无
 */
void OLED_ON(void)
{
    OLED_WriteCmd(0X8D); // 设置电荷泵
    OLED_WriteCmd(0X14); // 开启电荷泵
    OLED_WriteCmd(0XAF); // OLED唤醒
}

/**
 * 作用:  让OLED休眠 -- 休眠模式下,OLED功耗不到10uA
 * 参数: 无
 * 返回值: 无
 */
void OLED_OFF(void)
{
    OLED_WriteCmd(0X8D); // 设置电荷泵
    OLED_WriteCmd(0X10); // 关闭电荷泵
    OLED_WriteCmd(0XAE); // OLED休眠
}

/**
 * 作用:  OLED清屏
 * 参数: 无
 * 返回值: 无
 */
void OLED_Clear(void)
{
    uint8_t i, j;
    for (j = 0; j < 8; j++)
    {
        OLED_WriteCmd(0xb0 + i); // page0-page1
        OLED_WriteCmd(0x00);     // low column start address
        OLED_WriteCmd(0x10);     // high column start address
        for (i = 0; i < 128; i++)
        {
            OLED_WriteData(0x00);
        }
    }
}

/**
 * 作用: 在OLED上显示字符串
 * 参数x: 字符串显示的起始横坐标
 * 参数y: 字符串显示的起始纵坐标
 * 参数ch: 要显示的字符串
 * 参数TextSize: 字符大小，1表示6x8像素，2表示8x16像素
 * 返回值:无
 */
void OLED_ShowString(unsigned char x, unsigned char y, unsigned char ch[], unsigned char TextSize)
{
    unsigned char c = 0, i = 0, j = 0;

    switch (TextSize)
    {
    case 1:
    {
        // 遍历字符串
        while (ch[j] != '\0')
        {
            c = ch[j] - 32;
            // 如果超过屏幕宽度，换行显示
            if (x > 126)
            {
                x = 0;
                y++;
            }
            // 设置OLED显示位置
            OLED_SetPos(x, y);
            // 逐列写入6x8像素的字符数据
            for (i = 0; i < 6; i++)
            {
                OLED_WriteData(F6x8[c][i]);
            }
            x += 6; // 更新横坐标
            j++;
        }
    }
    break;
    case 2:
    {
        // 遍历字符串
        while (ch[j] != '\0')
        {
            c = ch[j] - 32;
            // 如果超过屏幕宽度，换行显示
            if (x > 120)
            {
                x = 0;
                y++;
            }
            // 设置OLED显示位置
            OLED_SetPos(x, y);
            // 逐列写入8x16像素的字符数据的上半部分
            for (i = 0; i < 8; i++)
            {
                OLED_WriteData(F8x16[c * 16 + i]);
            }
            // 设置OLED显示位置
            OLED_SetPos(x, y + 1);
            // 逐列写入8x16像素的字符数据的下半部分
            for (i = 0; i < 8; i++)
            {
                OLED_WriteData(F8x16[c * 16 + i + 8]);
            }
            x += 8; // 更新横坐标
            j++;
        }
    }
    break;
    }
}

/*
 * 作用:  OLED设置光标位置
 * 参数X: X 以左上角为原点，向右方向的坐标，范围：0~127
 * 参数Y: Y 以左上角为原点，向下方向的坐标，范围：0~7
 */
static void OLED_SetPos(uint8_t X, uint8_t Y)
{
    OLED_WriteCmd(0xb0 + Y);                 // 设置Y位置
    OLED_WriteCmd(0x10 | ((X & 0xF0) >> 4)); // 设置X位置高4位
    OLED_WriteCmd(0x01 | (X & 0x0F));        // 设置X位置低4位
}
